/**
 * @description 脚手架入口文件
 * @author zjat
 */

"use strict";

const path = require("path");
const semver = require("semver"); //对比版本号大小
const colors = require("colors/safe"); //提示颜色
const userHome = require("user-home"); //当前系统用户
const pathExists = require("path-exists").sync; //判断传递的路径是否存在
const log = require("@spiritos-cli/log"); //命令行自定义提示
const exec = require("@spiritos-cli/exec");
const commander = require("commander"); //初始化命令

//require: .js/.json/.node 如果不是以上文件 会已.js文件解析 如果文件内不是js代码则会报错
const packagejson = require("../package.json"); //获取packge.json文件内容
const constant = require("./const"); //获取常量

let args, config;
const program = new commander.Command(); //实例化commander

async function core() {
  try {
    await prepare();
    registerCommand();
  } catch (e) {
    log.error(e.message);
    if(program.opts().debug){
      console.error(e)
    }
  }
}

/**
 * 脚手架启动、准备阶段
 */
async function prepare(){
  checkPackageVersion();
  checkRoot();
  checkUserHome();
  checkEnv();
  await checkGlobalUpdate();
}

/**
 * 初始化命令、登记命令
 */
function registerCommand() {
  //全局;
  program
    .name(Object.keys(packagejson.bin)[0]) //脚手架名称
    .usage("<command> [options]")
    .version(packagejson.version) //注册版本号
    .option("-d, --debug", "是否开启调试模式", false) //全局属性
    .option("-tp, --targetPath <targetPath>", "是否置顶本地调试文件路径", "");

  //init 命令
  program
    .command("init [projectName]") //实现命令注册
    .option("-f, --force", "是否强制初始化项目")
    .action(exec);

  /**
   * 实现-d, --debug方法 开启debug模式
   */
  program.on("option:debug", function () {
    if (program.opts().debug) {
      process.env.LOG_LEVEL = "verbose";
    } else {
      process.env.LOG_LEVEL = "info";
    }
    log.level = process.env.LOG_LEVEL;
    log.verbose("test");
  });

  //监听targetPath命令
  program.on("option:targetPath",function(){
    process.env.CLI_TARGET_PATH = program.opts().targetPath;
  });

  /**
   * 对未知命令进行操作
   */
  program.on("command:*", function (obj) {
    const availableCommands = program.commands.map((cmd) => cmd.name());
    console.log(colors.red("未知的命令") + obj[0]);
    if (availableCommands.length > 0) {
      console.log(colors.red("可用命令") + availableCommands.join(","));
    }
  });

  //完成脚手架注册
  program.parse(process.argv);

  /**
   * 对未输入任何参数默认答应内容
   */
  if (program.args.length < 1 && program.args) {
    program.outputHelp();
    console.log();
  }
}

/**
 * 检查用户账号
 */
function checkRoot() {
  const rootCheck = require("root-check");
  rootCheck();
}

/**
 * 检查package版本号
 */
function checkPackageVersion() {
  log.info(packagejson.version, "cli");
}


/**
 * 检查用户主目录
 */
function checkUserHome() {
  if (!userHome || !pathExists(userHome)) {
    throw new Error(colors.red("当前用户主目录不存在"));
  }
}


/**
 * 检查环境变量
 */
function checkEnv() {
  const dotenv = require("dotenv");
  const dotenvPath = path.resolve(userHome, ".env");
  if (dotenvPath) {
    config = dotenv.config({
      path: dotenvPath,
    });
  }
  config = createDefaultConfig();
}

/**
 * 如果没有添加本地环境变量手动创建一下
 */
function createDefaultConfig() {
  const cliConfig = {
    home: userHome,
  };
  if (process.env.CLI_HOME_PAHT) {
    cliConfig["cliHome"] = path.join(userHome, process.env.CLI_HOME_PAHT);
  } else {
    cliConfig["cliHome"] = path.join(userHome, constant.DEFAULT_CLI_HOME);
  }
  return cliConfig;
}

/**
 * 本地版本是否与线上同步
 */
async function checkGlobalUpdate() {
  //1.获取当前版本号和模块名
  const currentVersion = packagejson.version;
  const npmName = packagejson.name;
  //2.调用npm api拿到线上版本号及模块名
  const { getNpmSemverVersions } = require("@spiritos-cli/get-npm-info");
  //3.提取所有版本号，对比那些版本号是大于当前版本号
  const lastVersion = await getNpmSemverVersions(npmName, currentVersion);
  if (lastVersion && semver.gt(lastVersion, currentVersion)) {
    log.warn(
      colors.yellow(
        `请手动更新${npmName},当前版本:${currentVersion},最新版本${lastVersion};更新命令:npm install -g ${npmName}`
      )
    );
  }
  //4.获取最新的版本号，提示用户更新到改版本号
}

module.exports = core;